pragma License (GPL);
--
-- drk-bigint-minus.adb
--
-- Copyright (C) 2012 - Thibault BUREL
--
-- This file is part of DRK.BigRat.
--
-- DRK.BigRat is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- DRK.BigRat is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with DRK.BigRat.  If not, see <http://www.gnu.org/licenses/>
--

separate(DRK.BigInt)
function Minus(Left  : in Instance;
               Right : in Instance) return Instance
is
   Result : Instance;

   CL : Digit_List.Cursor := Left.Mantissa.First;
   CR : Digit_List.Cursor := Right.Mantissa.First;

   L, R : Chunck;
   C    : Carry;

   procedure Internal_Substraction
   is
   begin

      --  With the modular arithmetic, in all cases we have :
      Result.Mantissa.Append (L - R - C);

      if R > L then
         C := 1;
      else
         if L - R >= C then
            C := 0;
         else
            C := 1;
         end if;
      end if;

   end Internal_Substraction;
   pragma Inline(Internal_Substraction);

begin

   if Left < Right then
      --  This branch is tested by Minus_01
      raise Underflow;

   end if;

   C := 0; -- At the beginning, no carry

   --  Since L >= R, the biggest mantissa is Left.
   while CR /= Digit_List.No_Element loop

      L := Digit_List.Element(CL);
      R := Digit_List.Element(CR);

      Internal_Substraction;

      CL := Digit_List.Next (CL);
      CR := Digit_List.Next (CR);

   end loop;

   R := 0;
   while CL /= Digit_List.No_Element loop

      L := Digit_List.Element(CL);

      Internal_Substraction;

      CL := Digit_List.Next (CL);

   end loop;

   --  According to the implementation choice, we have to suppress the leading
   --  0 digit.
   if Digit_List.Element (Digit_List.Last (Result.Mantissa)) = 0 then
      Digit_List.Delete_Last(Result.Mantissa);
   end if;

   --  This branch is tested by Minus_02
   return Result;

end Minus;
